/**
 *  The Yz.Upload prototype
 *
 */
(function(Yz) {
    if ( typeof(Yz) != "function" )
        throw "Failed to identify the root Yz object";

    // prevent multiple execution
    if ('Upload' in Yz)
        return;

    Yz.Upload = function(elName)
    {
        return this.init(elName);
    };


    /****************************
     *      Implementation      *
     ****************************/


    /**
     *  @access private
     *  @var Object/Hash { formName: handler }
     */
    Yz.Upload.handlers = {};
    Yz.Upload.timer = false;
    Yz.Upload.currentHandler = false;

    /** Create instance of Yz.Upload for the element elName or use the one already created
     *  @param string elName [REQUIRED]
     *  @return handler
     */
    Yz.Upload.createUpload = function(elName)
    {
        var handler = Yz.Upload.handlers[elName];
        if (! handler) {
            handler = new Yz.Upload(elName);
            Yz.Upload.handlers[elName] = handler;
        }
        return handler;
    }

    /** One upload form per page
     *  @return object {theDiv, theForm, theInput}
     */
    Yz.Upload.Form = function(action)
    {
        var self = Yz.Upload.Form;
        if (! ('theForm' in self)) {
            var div = document.createElement("DIV");
            div.innerHTML = "<form enctype='multipart/form-data' action='' method='POST' target='YzUploadFrame'>"
                + "<input type='file' name='theUpload' />"
                + "</form>"
                + "<iframe name='YzUploadFrame' id='YzUploadFrame' src='about:blank'"
                + ' style="border: 1px solid red; width: 250px; height: 100px"'
                + "></iframe>"
            self.theDiv = div
            self.theForm = div.getElementsByTagName("FORM")[0]
            self.theInput = div.getElementsByTagName("INPUT")[0]
            self.theFrame = div.getElementsByTagName("IFRAME")[0]
        }

        self.theInput.value = "";
        self.theForm.setAttribute("action", action);
        return self;
    }



    Yz.Upload.prototype = {
        sourceDiv: false,
        sourceInput: false,
        form: false,
        elName: false,
        uploadAction: false,
        deleteAction: false,

        /**
         *  the modified constructor: multiton, by form name
         *  Arguments: object {formName, inputName, success, failure}
         */
        init: function(elName)
        {
            this.sourceDiv = document.getElementById('yz-upload-' + elName);
            if (! this.sourceDiv)
                throw "Source DIV element not found";

            this.sourceInput = this.sourceDiv.getElementsByTagName("INPUT")[0];
            if (! this.sourceInput)
                throw "Source INPUT element not found";

            this.elName = elName;
            return this;
        } ,

        setUploadAction: function(uploadAction)
        {
            this.uploadAction = uploadAction;
            return this;
        },

        setDeleteAction: function(deleteAction)
        {
            this.deleteAction = deleteAction;
            return this;
        },


        /** Add the newly uploaded item's id to current values list
         *  @todo multiple values
         */
        addValue: function(val)
        {
            console.log("upload: add value '"+val+"'");
            this.sourceInput.value = val
            return this
        },

        /** Add the newly uploaded item's HTML representation to current
         *  @todo multiple values
         */
        addHTMLValue: function(html)
        {
            $(this.sourceDiv).find('div.yz-upload-value').html(html)
            return this
        },

        /**
         *  Show a dialog with the form and iframe
         *  @access private
         *  @param i18n {}
         *  @return Yz.Upload
         */
        showDialog: function(i18n)
        {
            console.log("upload: showDialog");
            var form = this.form = Yz.Upload.Form(this.uploadAction);

            var self = this;

            Yz.jqueryui(function(){
                var buttons = {};
                buttons[Yz.translate('Upload')] = function() { self.submit(form); }
                buttons[Yz.translate('Cancel')] = function() { $(this).dialog("close"); }
                $(form.theDiv).dialog({
                    modal: true,
                    title: i18n.title,
                    buttons: buttons
                });
            });
            return this;
        } ,

        /**
        *  the "user" function
        *
        */
        submit: function(form)
        {
            console.log("submit action:" + form.theForm.action);
            if ( form.theInput.value ) {
                this.startTimer().onFrameLoad(form.theFrame)
                    && form.theForm.submit();
            } else {
                Yz.Alert( Yz.translate('File not selected') );
            }
            return false;
        } ,

        /**
         *  @access private
         */
        startTimer: function()
        {
            console.log("start timer: " + Yz.Upload.timer);
            if ( false !== Yz.Upload.timer ) {
                // prevent multiple simultaneous file uploads
                Yz.Alert( Yz.translate("Please wait, upload in progress") );
                return false;
            }
            Yz.Upload.timer = setTimeout( this.timeout, 60000 );
            Yz.Upload.currentHandler = this;
            Yz.block();
            return this;
        } ,

        /**
         *  @access private
         */
        timeout: function()
        {
            Yz.Alert( Yz.translate("Upload timeout") );
            return Yz.Upload.currentHandler.done();
        } ,


        /**
         *  @access private
         */
        onFrameLoad: function(frame)
        {
            var self = this;
            $(frame).load(function(){
                console.log("UploadFrame loaded")
                // look for function 'uploadStatus()' in frame's namespace
                try {
                    // call in in the context of Yz.Upload instance
                    this.contentWindow.uploadStatus.call(self)
                } catch (ex) {
                    console.log("UploadFrame error: " + ex)
                    self.failure("Upload request failed")
                }
            })
            return this
        } ,

        /**
         *  @access private
         */
        success: function(text)
        {
            console.log("upload complete");
            Yz.Alert(text)
            return this.done();
        } ,

        /**
         *  @access private
         */
        failure: function(text)
        {
            console.log("upload failed");
            Yz.Alert(text)
            return this.done();
        } ,

        /**
         *  @access private
         */
        done: function()
        {
            console.log("upload done");
            if ( false !== Yz.Upload.timer )
                clearTimeout( Yz.Upload.timer );

            Yz.Upload.currentHandler = false;
            Yz.Upload.timer = false;
            Yz.unblock();
            $(this.form.theDiv).dialog('close')
            //Yz.Alert("Done");
            return this;
        }
    } // end prototype

})(window.Yz);

